package cn.gs.serializable.serialize;

// @author gs
import cn.gs.serializable.entity.IEntity;
import cn.gs.serializable.entity.OneEntity;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class ClassSerialize implements ISerialize {

    Map<String, Class> clsdef = new HashMap<String, Class>();
    Map<Class, String> strdef = new HashMap<Class, String>();

    public ClassSerialize() {
        namespaces = new LinkedList<String>();
        namespaces.add("java.lang.");
        namespaces.add("java.util.");
    }

    public ClassSerialize(String... names) {
        this();
        namespaces.addAll(0, Arrays.asList(names));
    }

    public ClassSerialize(Map<String, Class> defines) {
        this();
        for (Entry<String, Class> e : defines.entrySet()) {
            clsdef.put(e.getKey(), e.getValue());
            strdef.put(e.getValue(), e.getKey());
        }
    }
    private final List<String> namespaces;

    public Class forClass(String name) {
        //Full Name Check
        Class c;
        try {
            c = Class.forName(name);
            if (c != null) {
                return c;
            }
        } catch (ClassNotFoundException ex) {
        }
        //Check pre-defines
        c = clsdef.get(name);
        if (c != null) {
            return c;
        }
        //Check common namespace
        for (String ns : namespaces) {
            try {
                c = Class.forName(ns + name);
                if (c != null) {
                    return c;
                }
            } catch (ClassNotFoundException ex) {
            }
        }
        return null;
    }

    @Override
    public <T> T toObj(ISerialize ctrl, IEntity from, Class<T> clazz) {
        if (!(from instanceof OneEntity)) {
            return null;
        }
        if (Class.class.equals(clazz)) {
            String t = ((OneEntity) from).getValue();
            return (T) forClass(t);
        }
        return null;
    }

    public String forString(Class c) {
        String n;
        //Check pre-defines
        n = strdef.get(c);
        if (n != null) {
            return n;
        }
        //Check common namespace
        for (String ns : namespaces) {
            if ((ns + c.getSimpleName()).equals(c.getName())) {
                return c.getSimpleName();
            }
        }
        //Full Name
        return c.getName();
    }

    @Override
    public IEntity fromObj(ISerialize ctrl, Object o) {
        if (o == null || !(o instanceof Class)) {
            return null;
        }
        Class c = (Class) o;
        String n = forString(c);
        return new OneEntity(n, true);
    }
}
